package com.winchain.chainbill.acct.service.impl;

import com.shell.bee.acct.account.po.AcctBas;
import com.shell.bee.acct.account.po.AcctCard;
import com.shell.bee.base.service.BaseService;
import com.shell.bee.base.utils.JsonUtil;
import com.shell.bee.base.utils.SpringContextUtil;
import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.entity.mvc.RetMsg;
import com.shell.bee.persistence.annotation.Pagination;
import com.shell.bee.persistence.model.PageLimit;
import com.shell.bee.sequence.SequenceHelper;
import com.shell.constant.rel.AssetCode;
import com.shell.constant.rel.ConfigConstants;
import com.shell.framework.utils.CommonFileUtil;
import com.shell.plumber.PlumberReturns;
import com.shell.plumber.bank.BankExtFeign;
import com.winchain.chainbill.acct.dao.BankVirtualAcctDao;
import com.winchain.chainbill.acct.service.BankVirtualAcctService;
import com.winchain.chainbill.acct.vo.AcctVo;
import com.winchain.chainbill.basic.cus.po.CusRec;
import com.winchain.chainbill.basic.cus.service.CusRecService;
import com.winchain.chainbill.trade.service.BillAcctBlcService;
import com.winchain.chainbill.trade.service.BillAcctService;
import com.winchain.provider.expiration.vo.BatchStats;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service("bankVirtualAcctService")
public class BankVirtualAcctServiceImpl extends BaseService implements BankVirtualAcctService {
	@Autowired
	private BankVirtualAcctDao bankVirtualAcctDao;
	@Autowired
	private BillAcctService billAcctService;
	@Autowired
	private BillAcctBlcService billAcctBlcService;
	@Autowired
	private CusRecService cusRecService;
	@Autowired
	private BankExtFeign bankExtFeign;
	@Value("${cib.acctno.sequence.code}")
	private String cibSequenceCode;
	@Value("${cib.acctno.initial.value}")
	private String cibInitialValue;

	@Pagination
	public List<AcctVo> selectBankVirtualAcctList(PageLimit limit, AcctBas acctBas) {
		String custNm = acctBas.getCustNm();
		if (!StringUtil.emptyAndNull(custNm)) {
			acctBas.setCustNm(StringUtil.getParameterLike(custNm));
		}
		acctBas.setAcctType("1");
		acctBas.setOaaChnCode("B");
		return this.bankVirtualAcctDao.selectBankVirtualAcctList(acctBas);
	}

	public boolean changeState(String acctNo, String state) {
		AcctCard card = this.billAcctService.getCard(acctNo);
		card.setAcctSts(state);
		this.billAcctService.updateCard(card);
		return true;
	}

	public RetMsg batchOpen(String bankCode) throws IOException {
		AcctCard platformAcct = this.billAcctService.getPlatSpclAcct(bankCode);

		String virtualAcctUseStr = SpringContextUtil.getProperty("virtual.acct.use");
		String[] virtualAcctUses = StringUtil.emptyAndNull(virtualAcctUseStr) ? null : virtualAcctUseStr.split(",");
		List<String> useCodes = virtualAcctUses == null ? null : Arrays.asList(virtualAcctUses);

		CusRec tmp = new CusRec();
		tmp.setCusState("E");
		List<CusRec> cusList = this.cusRecService.selectByEntity(tmp);
		List<Map<String, Object>> params = new ArrayList();
		Map<String, Object> paramMap = null;
		Map<String, AcctCard> acctBasMap = new HashMap();
		String tmpAcctNo = null;
		for (CusRec cus : cusList) {
			tmpAcctNo = SequenceHelper.generateCode(this.cibSequenceCode, 6, Long.valueOf(this.cibInitialValue));
			AcctCard bas = addBankVirtualAcct(platformAcct, cus, useCodes, tmpAcctNo);
			if (bas != null) {
				paramMap = new LinkedHashMap();
				paramMap.put("acctNo", tmpAcctNo);
				paramMap.put("acctName", bas.getAcctNm());
				params.add(paramMap);
				acctBasMap.put(tmpAcctNo, bas);
			}
		}
		String paramsJson = "";
		try {
			paramsJson = JsonUtil.toJson(params);
		} catch (Exception e) {
			e.printStackTrace();
		}
		BatchStats<String> stats = new BatchStats();
		List<String> successAcctNos = null;
		List<String> errorMsgs = null;
		PlumberReturns<Map<String, List<String>>> ret;
		if (ConfigConstants.COOP_BANKS.contains(bankCode)) {
			ret = this.bankExtFeign.batchOpen(bankCode, paramsJson);
			successAcctNos = (List) ((Map) ret.getSource()).get("successAcctNos");
			errorMsgs = (List) ((Map) ret.getSource()).get("errorMsgs");
		} else {
			successAcctNos = new ArrayList();
			successAcctNos.addAll(acctBasMap.keySet());
			errorMsgs = new ArrayList();
		}
		for (String acctNo : successAcctNos) {
			AcctCard bas = (AcctCard) acctBasMap.get(acctNo);
			bas.setCurrCode(AssetCode.CNY.name());
			bas.setInitBkp(false);
			this.billAcctService.addCard(bas);
			stats.addPassedRecord(acctNo);
		}
		if (params.size() == successAcctNos.size()) {
			return new RetMsg("success", true, "��������������");
		}
		if (stats.getAffectedRows() == 0) {
			return new RetMsg("error", true, "��������������", CommonFileUtil.changMsg(errorMsgs));
		}
		return new RetMsg("warning", true, "������������������", CommonFileUtil.changMsg(errorMsgs));
	}

	public BatchStats<String> syncAcctBlc(String... acctNoArr) {
		BatchStats<String> stats = new BatchStats();
		for (String acctNo : acctNoArr) {
			PlumberReturns<BigDecimal> ret = this.billAcctBlcService.getBankAcctBlc(acctNo);
			if ((ret != null) && ("S".equals(ret.getRspCode()))) {
				stats.addPassedRecord(acctNo);
			} else {
				stats.addAbnormalRecord(acctNo);
				stats.addAbnormalMsg(ret.getMessage());
			}
		}
		return stats;
	}

	private AcctCard addBankVirtualAcct(AcctCard platformAcct, CusRec cus, List<String> useCodes, String acctNo) {
		AcctCard card = new AcctCard();
		card.setAcctType("1");
		card.setOaaChnCode("B");
		card.setFiNo(platformAcct.getFiNo());
		card.setCustId(cus.getCusId());
		card = this.billAcctService.getAcctCard(card);
		if (card == null) {
			card = new AcctCard();
			card.setAcctNo(platformAcct.getAcctNo() + acctNo);
			card.setAcctNm(cus.getCusName());
			card.setHqFiNo(platformAcct.getHqFiNo());
			card.setHqFiNm(platformAcct.getHqFiNm());
			card.setFiNo(platformAcct.getFiNo());
			card.setFiNm(platformAcct.getFiNm());
			card.setFiPrvnNm(platformAcct.getFiPrvnNm());
			card.setFiCityNm(platformAcct.getFiCityNm());

			card.setCustId(cus.getCusId());
			card.setCustNm(cus.getCusName());
			card.setUseCodes(useCodes);

			card.setAcctType("1");
			card.setOaaChnCode("B");
			card.setCustAcctType("C");
			return card;
		}
		return null;
	}
}
